﻿using System;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Json;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Xml;
using Microsoft.VisualBasic.Devices;
using Entidades;
using Logica.WebServices_BCR;
using Entidades.Model;
using Logica.WebServices_BCR;

namespace DuplicateCheckService
{
    public partial class DuplicateCheckService : ServiceBase
    {
        //private ScheduleService _serviceSchedule;
        delegate void AsyncMethodCaller();
        bool Continue = true;
        public DuplicateCheckService()
        {
            InitializeComponent();
        }

        #region Verify Configuration
        private bool verifyconfiguration()
        {
            #region Parameters not null

            if (Configuration.beginTime <= 0)
            {
                Services.sendLog(63, "El parametro delay debe ser mayor a cero", Services.errorType.Error_Message);
                return false;
            }

            if (Configuration.endTime.Equals(""))
            {
                Services.sendLog(64, "El parametro schedulesTimes no puede estar en blanco", Services.errorType.Error_Message);
                return false;
            }

            if (Configuration.inputQueue.Equals(""))
            {
                Services.sendLog(64, "El parametro inputQueue no puede estar en blanco", Services.errorType.Error_Message);
                return false;
            }

            if (Configuration.readCommand.Equals(""))
            {
                Services.sendLog(64, "El parametro readCommand no puede estar en blanco", Services.errorType.Error_Message);
                return false;
            }

            if (Configuration.readCommandParameter.Equals(""))
            {
                Services.sendLog(64, "El parametro readCommandParameter no puede estar en blanco", Services.errorType.Error_Message);
                return false;
            }

            if (Configuration.updateCommand.Equals(""))
            {
                Services.sendLog(64, "El parametro updateCommand no puede estar en blanco", Services.errorType.Error_Message);
                return false;
            }

            if (Configuration.updateHistoricoParameter.Equals(""))
            {
                Services.sendLog(64, "El parametro updateHistoricoParameter no puede estar en blanco", Services.errorType.Error_Message);
                return false;
            }

            if (Configuration.updateIDParameter.Equals(""))
            {
                Services.sendLog(64, "El parametro updateIDParameter no puede estar en blanco", Services.errorType.Error_Message);
                return false;
            }

            if (Configuration.updateVersionParameter.Equals(""))
            {
                Services.sendLog(64, "El parametro updateVersionParameter no puede estar en blanco", Services.errorType.Error_Message);
                return false;
            }

            if (Configuration.systemID.Equals(""))
            {
                Services.sendLog(64, "El parametro systemID no puede estar en blanco", Services.errorType.Error_Message);
                return false;
            }

            if (Configuration.emailAccountTo.Equals(""))
            {
                Services.sendLog(64, "El parametro emailAccountTo no puede estar en blanco", Services.errorType.Error_Message);
                return false;
            }

            #endregion

            if (!(this.verifyLogsZone()))
                return false;            

            if (!(this.verifyInfoImageZone()))
                return false;

            if (!(this.verifyDataBaseZone()))
                return false;  

            return true;

        }

        private bool verifyLogsZone()
        {
            try
            {
                /*String registry = "HKEY_LOCAL_MACHINE\\Software\\Unisys\\Unisys Duplicate Check";

                bool varTemp;                
                varTemp = Boolean.Parse(Microsoft.Win32.Registry.GetValue(registry, "Error_Message", false).ToString());
                varTemp = Boolean.Parse(Microsoft.Win32.Registry.GetValue(registry, "Log_Message", false).ToString());
                varTemp = Boolean.Parse(Microsoft.Win32.Registry.GetValue(registry, "Information_Message", false).ToString());
                varTemp = Boolean.Parse(Microsoft.Win32.Registry.GetValue(registry, "Proccess_Message", false).ToString());
                
                varTemp = Boolean.Parse(Microsoft.Win32.Registry.GetValue(registry, "FileSystemLog", false).ToString());*/

                //if (varTemp)
                    if (!(System.IO.Directory.Exists(Configuration.logLocation)))
                        System.IO.Directory.CreateDirectory(Configuration.logLocation);

                if (Configuration.logMaxSizeBytes <= 0)
                    return false;

                return true;
            }
            catch (Exception e)
            {
                Datos.Logger.Logger.LogThis4Windows("Error al intentar leer la configuracion de la aplicacion " + e.Message, "Unisys Duplicate Check", "Unisys Duplicate Check");
                return false;
            }
        }

        private bool verifyInfoImageZone()
        {            
            Services.sendLog(519,"Verificando Sección de IIF.",Services.errorType.Information_Message);
            Logica.InfoImage_Folder.IIF_Connection infoImage = new Logica.InfoImage_Folder.IIF_Connection();

            if (infoImage.CreateIIFClient(Configuration.IIFUser, Configuration.IIFPassword, Configuration.IIFDomain))
            {
                Services.sendLog(260, "Conexion con IIF establecida: usuario " + Configuration.IIFUser + " conectado con exito", Services.errorType.Information_Message);
                
                infoImage.DestroyIIFClientExplicit();
                Services.sendLog(261, "Desconexion con IIF realizada con exito", Services.errorType.Information_Message);

            }
            else
            {
                Services.sendLog(57, "No se pudo realizar la conexion con IIF: usuario " + Configuration.IIFUser + " no conectado, revisar log.", Services.errorType.Error_Message);                
                return false;
            }
            Services.sendLog(521, "Seccion de IIF ok", Services.errorType.Information_Message);

            return true;           
        }

        private bool verifyDataBaseZone()
        {
            try
            {
                Datos.Data_Base.SqlDataClass dataClass= new Datos.Data_Base.SqlDataClass();                
                dataClass.OpenConnection();
                Services.sendLog(257, "Conexion de BD abierta con éxito", Services.errorType.Information_Message);                
                dataClass.CloseConnection();
                Services.sendLog(258, "Conexion de BD cerrada sin problemas", Services.errorType.Information_Message);
                Services.sendLog(514, "Seccion de BD ok", Services.errorType.Information_Message);                
                return true;
            }
            catch (Exception e)
            {
                Services.sendLog(151, "Imposible conectar con la bd", Services.errorType.Error_Message,e);
                return false;
            }
        }
        #endregion

        private string arrayToString(string[] array)
        {
            string resp = "";
            for(int i=0;i<array.Length;i++)
            {
                if (i == (array.Length - 1))
                    return resp + array[i];
                else
                    resp += array[i] + ",";
            }
            return resp;
        }

        protected override void OnStart(string[] args)
        {
            #region Load Configuration
            try
            {
                Configuration.Load();
                
                if (!(this.verifyconfiguration()))
                {
                    Datos.Logger.Logger.LogThis4Windows("Error al intentar leer la configuracion de la aplicacion. La verificacion de la configuracion"+
                    " no ha finalizado con exito, favor revise la configuracion", "Unisys Duplicate Check", "Unisys Duplicate Check");
                    System.Environment.Exit(0);
                }
            }
            catch (Exception e)
            {
                Datos.Logger.Logger.LogThis4Windows("Error al intentar leer la configuracion de la aplicacion " + e.Message, "Unisys Duplicate Check", "Unisys Duplicate Check");
                System.Environment.Exit(0);
            }

            Services.sendLog(530,"El sistema de duplicados ha levantado su configuracion", Services.errorType.Log_Message,null,"Inicio del Servicio");


            Services.sendLog(530, "Configuracion cargada correctamente con los siguientes parametros:\n logLocation: ["+Configuration.logLocation+"]"+
                "\n logMaxSizeBytes: ["+Configuration.logMaxSizeBytes+"] \n IIFDomain: ["+Configuration.IIFDomain+"] \n IIFUser: ["+Configuration.IIFUser+"]"+
                "\n inputQueue: ["+Configuration.inputQueue+"] \n beginTime: ["+Configuration.beginTime+"] \n endTime: ["+Configuration.endTime+"]"+
                "\n searchQueues: [" + this.arrayToString(Configuration.searchQueues) + "] \n readCommand: [" + Configuration.readCommand + "] \n readParameter: [" + Configuration.readCommandParameter + "]"+
                "\n updateCommand: [" + Configuration.updateCommand + "] \n updateID: [" + Configuration.updateIDParameter + "] \n updateVersion: [" + Configuration.updateVersionParameter + "] \n updateHistorico: [" + Configuration.updateHistoricoParameter + "] \n systemID: " +
                "[" + Configuration.systemID + "] \n emailAccountTo: [" + this.arrayToString(Configuration.emailAccountTo) + "]",
                Services.errorType.Information_Message);

            #endregion

            AsyncMethodCaller caller = new AsyncMethodCaller(checkTime);

            // Initiate the asychronous call.
            
            IAsyncResult result = caller.BeginInvoke(null, null);

            //definir calendarizacion
            /*Logica.Administrator admin=new Logica.Administrator();
            admin.processManager();*/
        }


        public void checkTime()
        {
            while (Continue)
            {
                int now = Convert.ToInt32(DateTime.Now.ToString("HHmm"));
                bool beginProcess = true;
                Logica.WebServices_BCR.Services.sendLog(646, "Hora de Inicio: "+now, Logica.WebServices_BCR.Services.errorType.Information_Message);
                if ((now >= Configuration.beginTime) && (now < Configuration.endTime))
                {
                    Logica.WebServices_BCR.Services.sendLog(645, "La hora se encuentra dentro del margen de hora ejecucion " + now, Logica.WebServices_BCR.Services.errorType.Information_Message);

                    Logica.Administrator admin = new Logica.Administrator();
                    admin.processManager();
                    Logica.WebServices_BCR.Services.sendLog(292, "Proceso Finalizado con exito", Logica.WebServices_BCR.Services.errorType.Information_Message);
                    beginProcess = true;
                }
                else
                {
                    beginProcess = false;
                    Logica.WebServices_BCR.Services.sendLog(647, "La hora no se encuentra dentro del margen de hora ejecucion", Logica.WebServices_BCR.Services.errorType.Information_Message);
                }
                

                if (!(beginProcess))
                {
                    if (Configuration.beginTime > now)//la hora no ha pasado en el dia
                    {
                        double sleepTime = (new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, Convert.ToInt32(Configuration.beginTime.ToString().Substring(0, 2)), Convert.ToInt32(Configuration.beginTime.ToString().Substring(2)), 0)).Subtract(DateTime.Now).TotalMilliseconds;
                        Logica.WebServices_BCR.Services.sendLog(646, "El proceso reiniciara en: "+sleepTime+" Milisegundos", Logica.WebServices_BCR.Services.errorType.Information_Message);
                        Thread.Sleep((int)sleepTime);//espera un minuto
                    }
                    else
                    {
                        //la hora ya paso, se espera a mañana
                        double sleepTime = (new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, Convert.ToInt32(Configuration.beginTime.ToString().Substring(0, 2)), Convert.ToInt32(Configuration.beginTime.ToString().Substring(2)), 0)).AddDays(1).Subtract(DateTime.Now).TotalMilliseconds;
                        Logica.WebServices_BCR.Services.sendLog(646, "El proceso reiniciara en: " + sleepTime + " Milisegundos", Logica.WebServices_BCR.Services.errorType.Information_Message);
                        Thread.Sleep((int)sleepTime);//espera un minuto
                    }

                }
            }
        }

        protected override void OnStop()
        {
            Continue = false;
        }
    
    }
}
